using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace MetarCommonSupport.SNMP
{
	class  TimerUdpClient: UdpClient
	{
		public TimerUdpClient():base()
		{
			Client.Bind((EndPoint)(new IPEndPoint(IPAddress.Any,0))); 
		}
		public TimerUdpClient(AddressFamily l):base(l)
		{
			Client.Bind((EndPoint)(new IPEndPoint(IPAddress.Any,0)));
		}	
		public TimerUdpClient(int l):base(l)
		{
		}	
		public TimerUdpClient(IPEndPoint l):base(l)
		{
		}	
		public TimerUdpClient(int l1, AddressFamily l2):base(l1,l2)
		{
		}
		public TimerUdpClient(string l1, int l2):base(l1,l2)
		{
		}


		public byte[] Receive(ref IPEndPoint remoteEP,int timeout)
		{
			StateObject	so = new StateObject();
			so.ep	   = remoteEP;
			EndPoint ep = (EndPoint)so.ep;

//			IPEndPoint ep1 = new IPEndPoint(IPAddress.Any,0);
//			ep = (EndPoint)ep1;

			try
			{
				Client.BeginReceiveFrom(so.buffer,0,1024*500,0,ref ep,new AsyncCallback(myReceiveCallback),so);
			}
			catch
			{
				return null;
			}

			if(so.m_event.WaitOne(timeout,true))
			{
				if(so.len>0)
				{
					byte[] buffer=new byte[so.len];
					for(int i=0;i<so.len;i++)
						buffer[i]=so.buffer[i];
					return buffer;
				}
				else
				{
					return null;
				}
			}
			else
			{
				return null;
			}
		}
		private void myReceiveCallback(IAsyncResult ar)
		{
			StateObject	so=(StateObject)ar.AsyncState;
			EndPoint ep=(EndPoint)so.ep;

			if(this.Client != null)
			{
				try
				{
					so.len=Client.EndReceiveFrom(ar,ref ep);
				}
				catch
				{
					so.len	= 0;
				}
			}
			else
				so.len	= 0;
			so.m_event.Set();
		}


		private class StateObject
		{
			public byte[] buffer=new byte[1024*500];
			public int	  len=0;

			public IPEndPoint ep=new IPEndPoint(IPAddress.Any,0);
			public ManualResetEvent m_event=new ManualResetEvent(false);
		}

	}
}
